/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package assignment2.pkg1;

import java.io.IOException;
import java.util.Random;
import statistics.Distribution;
import statistics.ExponentialDistribution;

/**
 *
 * @author MBoon
 */
public class GGcSim {

    private Distribution interArrivalTimeDistribution, serviceTimeDistribution;
    private int nServers;
    
    public GGcSim(Distribution interArrivalTimeDistribution, 
            Distribution serviceTimeDistribution, int nServers) {
        this.interArrivalTimeDistribution = interArrivalTimeDistribution;
        this.serviceTimeDistribution = serviceTimeDistribution;
        this.nServers = nServers;
    }
    
    public SimResults simulate(int N) {
        // initialisation
        Queue q = new Queue();
        ServerPool servers = new ServerPool(nServers);
        FES fes = new FES();
        SimResults results = new SimResults(N);
        int n = 0; // number of customers simulated so far
        
        // schedule the first events
        Event event1 = new Event(interArrivalTimeDistribution.nextRandom(), Event.ARRIVAL);
        fes.add(event1);
    
        while (n < N) {
            Event e = fes.nextEvent();
            double t = e.getTime();
            results.registerNumberOfCustomersInSystem(q.getSize()+servers.numberOfCustomersInService(), t);
            int type = e.getType();
            
            if (type == Event.ARRIVAL) {  // arrival event
                Customer c = new Customer(t);
                q.addCustomer(c);
                if ( servers.serverAvailable() ) {
                    q.removeFirstCustomer();
                    servers.addCustomer(c);
                    Event dep = new Event(t + serviceTimeDistribution.nextRandom(), 
                        Event.DEPARTURE,c);
                    fes.add(dep);
                    results.registerWaitingTime(0);
                    n++;
                }
                // schedule next arrival
                Event nextArr = new Event(t + interArrivalTimeDistribution.nextRandom(), Event.ARRIVAL);
                fes.add(nextArr);
            }
            else {   // departure event
                Customer leavingCust = e.getCustomer();
                servers.removeCustomer(leavingCust);
                if (!q.isEmpty()) {
                    Customer c = q.removeFirstCustomer();
                    servers.addCustomer(c);
                    Event dep = new Event(t + serviceTimeDistribution.nextRandom(), 
                        Event.DEPARTURE,c);
                    fes.add(dep);
                    
                    
                    results.registerWaitingTime(t - c.getArrivalTime());
                    n++;
                }
                
            }         
        }
        return results;
    }
    
    
    
    
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        double lambda = 4;
        double mu = 0.9;
        int nServer = 5;
        Random rng = new Random();
        ExponentialDistribution a = new ExponentialDistribution(lambda, rng);
        ExponentialDistribution b = new ExponentialDistribution(mu, rng);
        GGcSim sim = new GGcSim(a, b, nServer);
        SimResults results = sim.simulate(10000);
        double w = results.getMeanWaitingTime();
        //System.out.println(w);
        double[] q1Probs = results.getQueueLengthProbabilities(nServer);
        for(int i=0; i<20; i++){
            System.out.println(q1Probs[i]+",");
        }
        results.export("testFile");
    }
    
}
